﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Singer.BackgroundJob.RabbitMQ.BackgroundJobLogs;
using Singer.BackgroundJob.RabbitMQ.Contracts;
using Singer.Middleware.RabbitMQ;
using System.Reflection;

namespace Singer.BackgroundJob.RabbitMQ;

/// <summary>
/// 后台任务 服务拓展
/// </summary>
public static class BackgroundJobServiceExtensions
{
    /// <summary>
    /// 注入基于RabbitMQ的后台任务服务，并记录当前程序集中的所有任务处理器
    /// </summary>
    /// <param name="jobExecutorsAssemblys">后台任务执行器所在的程序集</param>
    public static void AddRabbitMQBackgroundJob(this IServiceCollection services, IConfiguration configuration, params Assembly[] jobExecutorsAssemblys)
    {
        // 解析 后台任务配置
        var config = configuration.GetSection(BackgroundJobOptions.ConfigKey);
        BackgroundJobOptions? options = config.Get<BackgroundJobOptions>();
        if (options == null)
            throw new Exception("【BackgroundJob.RabbitMQ】Config was not found.");
        services.Configure<BackgroundJobOptions>(config);

        Type baseExecutorType = typeof(BackgroundJobExecutorBase);
        // 找到程序集中所有的后台任务执行器类，注册为作用域服务。并将执行器的信息解析为后台任务消费者上下文列表，注册为单例服务。
        List<ConsumerContext> consumers = [];
        try
        {
            foreach (Assembly assembly in jobExecutorsAssemblys)
            {
                foreach (Type executorType in assembly.GetTypes().Where(x => !x.IsAbstract && baseExecutorType.IsAssignableFrom(x)))
                {
                    var executorAttribute = executorType.GetCustomAttribute<BackgroundJobExecutorAttribute>();
                    if (executorAttribute == null)
                        continue;
                    if (!consumers.Any(x => x.ArgsType == executorAttribute!.ArgsType))
                    {
                        consumers.Add(new ConsumerContext(executorAttribute!.ArgsType, executorType, executorAttribute));
                        services.Replace(new ServiceDescriptor(executorType, executorType, ServiceLifetime.Scoped)); // 将后台任务执行器，注册为作用域服务
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw new Exception($"【BackgroundJob.RabbitMQ】The job executors services resolving failed. ErrorMessage：" + ex.Message);
        }

        services.AddRabbitMQ(configuration); // 注入RabbitMQ连接池服务
        services.AddSingleton(new BackgroundJobConsumerCollection(consumers)); // 将后台任务消费者上下文列表，注册为单例服务
        services.AddScoped<IBackgroundJobLogRepository, BackgroundJobLogRepository>(); // 后台任务日志仓储服务
        services.AddScoped<IBackgroundJobLogDetailRepository, BackgroundJobLogDetailRepository>(); // 后台任务日志详情仓储服务
        services.AddScoped<BackgroundJobLogManager>(); // 后台任务日志领域服务
        services.AddScoped<IBackgroundJobTrigger, BackgroundJobTrigger>(); // 后台任务触发器服务
        services.AddHostedService<BackgroundJob>(); // 注册后台托管任务
    }
}
